package org.imlinker.buddy;

import java.util.Collection;

import org.imlinker.gui.ChatWindow;
import org.imlinker.list.ViewList;
import org.imlinker.login.Account;
import org.imlinker.chat.PluginChat;

import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.packet.Presence;

/**
 * The chat information of buddy.
 * 
 */

public class BuddyChat {
	/**
	 * The status information of the buddy.
	 */
	private String status;

	/**
	 * The buddy user id. ie. "test@gmail.com".
	 */
	private String buddyUser;

	/**
	 * The nick name of the buddy.
	 */
	private String buddyName;

	/**
	 * The log record when the Chat window is closed.
	 */
	private StringBuffer chatLog = new StringBuffer("");

	/**
	 * The refer of chat used to send and receive message from the buddy.
	 */
	private Chat savedChat;

	/**
	 * The chatWindow used to display the chat information.
	 */
	private ChatWindow chatWindow = null;

	/**
	 * The roster buddy's entry.
	 */
	private RosterEntry localEntry = null;

	/**
	 * The composing string used to display when the buddy is composing.
	 * 
	 * TODO translate :)
	 */
	private static String composingFlag = "composing";

	/**
	 * The composing flag.
	 */
	private boolean composing = false;

	/**
	 * The buddyItem.
	 */
	private BuddyItem buddyItem;

	/**
	 * 
	 * @param paraBuddyItem
	 *            The buddy's entry.
	 */
	public BuddyChat(final BuddyItem paraBuddyItem) {
		RosterEntry entry = paraBuddyItem.getEntry();

		this.buddyItem = paraBuddyItem;
		this.localEntry = entry;

		buddyUser = entry.getUser();
		buddyName = entry.getName();
		if (buddyName == null) {
			buddyName = buddyUser;
		}

	}

	/**
	 * The receive function.
	 * 
	 * @param message
	 *            The received message
	 */
	public final void recieve(final Message message) {
		if (message.getBody() == null) {
			if (chatWindow == null) {
				return;
			}

			Collection<PacketExtension> extens = message.getExtensions();
			for (PacketExtension p : extens) {
				if (p.getElementName().equals(composingFlag)) {
					chatWindow.setTitle("Link to " + buddyName + " "
							+ composingFlag);
					composing = true;
					return;
				}
			}

			if (composing) {
				chatWindow.setTitle("Link to " + buddyName);
				composing = false;
			}

			return;
		}

		// Pass received message to plugin.
		String ret = PluginChat.passChatMessage(message);
		// if (!ChatHook.passChatMessage(message))
		// displayMessage(buddyName + ":" + message.getBody());
		if (ret == null) {
			displayMessage(buddyName + ":" + message.getBody());
		} else if (ret.indexOf("LINKERNOCHAT") < 0) {
			displayMessage(ret);
		}
	}

	/**
	 * Send message.
	 * 
	 * @param message
	 *            The message to be send.
	 */
	public final void send(final String message) {
		try {
			savedChat.sendMessage(message);

			// Create new Message for pass.
			Message m = new Message();
			m.setBody("You:" + message);
			m.setTo(savedChat.getParticipant());
			m.setFrom("");

			// if passChatMessage() return false, display the message.
			PluginChat.passChatMessage(m);

			// Display
			displayMessage(Account.getUserName() + ":" + message);

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Display message, if chatWindow is on.let chatWindow display this. // If
	 * chatWindow is off, save the message in ChatLog.
	 * 
	 * @param body
	 *            The information to display.
	 */
	public final void displayMessage(final String body) {
		if (chatWindow != null) {
			// ChatWindow is on.
			chatWindow.display(body);

			if (!chatWindow.isVisible()) {
				ViewList.addMessage(buddyItem);
			}
		} else {
			// ChatWindow is off.

			ViewList.addMessage(buddyItem);

			// Add message to chatLog.
			if (chatLog.length() == 0) {
				chatLog.append(body);
			} else {
				chatLog.append("\n");
				chatLog.append(body);
			}
		}
	}

	/**
	 * Get buddy's status information.When it's not null. Add "()".
	 * 
	 * @return The buddy'status.
	 */
	public final String getStatus() {
		if (status != null && status.trim().length() > 0) {
			return "(" + status + ")";
		}

		return "";
	}

	/**
	 * Change chatCell status by received presence.
	 * 
	 * @param presence
	 *            The received presence.
	 */
	public final void setPresence(final Presence presence) {
		status = presence.getStatus();
	}

	/**
	 * Get saved chat log.
	 * 
	 * @return The saved chat log.
	 */
	public final String getChatLog() {
		String temp = new String(chatLog);
		chatLog = new StringBuffer("");

		return temp;
	}

	/**
	 * doubleClick for BuddyList.
	 */
	public final void doubleClick() {

		// Create chatWindow and remove message notify if it has.
		if (chatWindow == null) {
			chatWindow = new ChatWindow(BuddyChat.this);
			chatWindow.setIconImage(buddyItem.getIcon().getImage());

		} else {
			chatWindow.showWindow();
		}

		ViewList.removeMessage(buddyItem);

		// Create chat to send message.
		if (savedChat == null) {
			savedChat = BuddyList.createChat(buddyUser);
		}
	}

	/**
	 * Get the buddy's user id.
	 * 
	 * @return The buddy's user id.
	 */
	public final String getUser() {
		return buddyUser;
	}

	/**
	 * Get the buddy's nick name.
	 * 
	 * @return The buddy's nick name.
	 */
	public final String getName() {
		return buddyName;
	}

	/**
	 * Change buddy name.
	 * 
	 * @param name
	 *            The name used to replace the buddy's current name.
	 */
	public final void setBuddyName(final String name) {
		localEntry.setName(name);
		buddyName = name;
		// this will refresh the window's title
		// when you change buddy's name
		if (chatWindow != null) {
			chatWindow.setTitle("Link to " + buddyName);
		}
	}

	/**
	 * Set chat.
	 * 
	 * @param chat
	 *            The chat should be saved.
	 * 
	 */
	public final void setChat(final Chat chat) {
		this.savedChat = chat;
	}

	/**
	 * 
	 * @return The chatWindow
	 */
	public final ChatWindow getChatWindow() {
		return chatWindow;
	}

}
